#include <stdio.h>
#include <stdlib.h>
#include "List.h"


struct list {
	ListNode*   header;
};


struct listNode {
	ElemType    data;
	ListNode*   next;
};


int ListInit(List* list) {
	list->header = (ListNode*) malloc(sizeof(ListNode));
	if (list->header == NULL) {
		return 1;
	}
	list->header->data = 0;
	list->header->next = NULL;
	return 0;
}


int ListInsertAfter(ListNode* node, ElemType elem) {
	ListNode* newNode = (ListNode*) malloc(sizeof(ListNode));
	if (newNode == NULL) {
		return 1;
	}
	newNode->data = elem;
	newNode->next = node->next;
	node->next = newNode;
	return 0;
}


int ListPrint(List* list) {
	for (ListNode* node = list->header->next; node != NULL; node = node->next) {
		printf("%d ", node->data);
	}
	printf("\n");
	return 0;
}


int ListLength(List* list) {
	int cnt = 0;
	for (ListNode* node = list->header->next; node != NULL; node = node->next) {
		cnt += 1;
	}
	return cnt;
}


int ListPop(List* list, ListNode* node) {
	ListNode* prevNode = list->header;
	for (; prevNode != NULL && prevNode->next != node; prevNode = prevNode->next) {}
	if (prevNode == NULL) {
		return 1;
	}
	prevNode->next = node->next;
	free(node);
	return 0;
}


int ListClear(List* list) {
	ListNode* current = list->header->next;
	ListNode* next;
	while (current != NULL) {
		next = current->next;
		free(current);
		current = next;
	}
	list->header->next = NULL;
	return 0;
}


ListNode* ListLocate(List* list, ElemType elem) {
	for (ListNode* node = list->header->next; node != NULL; node = node->next) {
		if (node->data == elem) {
			return node;
		}
	}
	return NULL;
}


int ListDetail(List* list) {
	printf("List header: %p\n", list->header);
	printf("%-25s %-15s %-25s\n", "Node Address", "Data", "Next Node Address");
	for (ListNode* node = list->header; node != NULL; node = node->next) {
		printf("%-25p %-15d %-25p\n", node, node->data, node->next);
	}
	return 0;
}


int ListDestroy(List* list) {
	ListNode* current = list->header;
	ListNode* next;
	while (current != NULL) {
		next = current->next;
		free(current);
		current = next;
	}
	list->header = NULL;
	return 0;
}


int main() {
	List list;
	ListInit(&list);
	printf("Length: %d\n", ListLength(&list));
	for (int x = 1; x <= 100; x += 1) {
		ListInsertAfter(list.header, x);
	}
	ListPrint(&list);
	printf("Length: %d\n", ListLength(&list));
	for (int x = 0; x < 95; x += 1) {
		ListPop(&list, list.header->next);
	}
	ListDetail(&list);
	printf("Length: %d\n", ListLength(&list));
	printf("Address of 3 is %p.\n", ListLocate(&list, 3));
	ListClear(&list);
	ListPrint(&list);
	printf("Length: %d\n", ListLength(&list));
	return 0;
}
